<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/11/2
 * Time: 10:52
 */

namespace App\CorePlugs\IpQuery;


class IpQuery
{
    private static $qqwry_path = "";
    //
    public static function convertString($ip)
    {
        $return = '';
        // $ip = "135.20.1.5";
        if (preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
            $iparray = explode('.', $ip);
            if ($iparray[0] == 10 || $iparray[0] == 127 || ($iparray[0] == 192 && $iparray[1] == 168) || ($iparray[0] == 172 && ($iparray[1] >= 16 && $iparray[1] <= 31))) {
                $return = 'LAN';
            } elseif ($iparray[0] > 255 || $iparray[1] > 255 || $iparray[2] > 255 || $iparray[3] > 255) {
                $return = 'Invalid IP Address';
            } else {
                $ipdatafile = IpQuery::$qqwry_path;
                if (!$fd = @fopen($ipdatafile, 'rb')) {
                    return 'Invalid IP data file';
                }
                $ip = explode('.', $ip);
                $ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
                if (!($DataBegin = fread($fd, 4)) || !($DataEnd = fread($fd, 4))) {
                    return;
                }

                @$ipbegin = implode('', unpack('L', $DataBegin));
                if ($ipbegin < 0) {
                    $ipbegin += pow(2, 32);
                }

                @$ipend = implode('', unpack('L', $DataEnd));
                if ($ipend < 0) {
                    $ipend += pow(2, 32);
                }

                $ipAllNum = ($ipend - $ipbegin) / 7 + 1;
                $BeginNum = $ip2num = $ip1num = 0;
                $ipAddr1 = $ipAddr2 = '';
                $EndNum = $ipAllNum;
                while ($ip1num > $ipNum || $ip2num < $ipNum) {
                    $Middle = intval(($EndNum + $BeginNum) / 2);
                    fseek($fd, $ipbegin + 7 * $Middle);
                    $ipData1 = fread($fd, 4);
                    if (strlen($ipData1) < 4) {
                        fclose($fd);
                        return 'System Error';
                    }
                    $ip1num = implode('', unpack('L', $ipData1));
                    if ($ip1num < 0) {
                        $ip1num += pow(2, 32);
                    }

                    if ($ip1num > $ipNum) {
                        $EndNum = $Middle;
                        continue;
                    }
                    $DataSeek = fread($fd, 3);
                    if (strlen($DataSeek) < 3) {
                        fclose($fd);
                        return 'System Error';
                    }
                    $DataSeek = implode('', unpack('L', $DataSeek . chr(0)));
                    fseek($fd, $DataSeek);
                    $ipData2 = fread($fd, 4);
                    if (strlen($ipData2) < 4) {
                        fclose($fd);
                        return 'System Error';
                    }
                    $ip2num = implode('', unpack('L', $ipData2));
                    if ($ip2num < 0) {
                        $ip2num += pow(2, 32);
                    }

                    if ($ip2num < $ipNum) {
                        if ($Middle == $BeginNum) {
                            fclose($fd);
                            return 'Unknown';
                        }
                        $BeginNum = $Middle;
                    }
                }
                $ipFlag = fread($fd, 1);
                if ($ipFlag == chr(1)) {
                    $ipSeek = fread($fd, 3);
                    if (strlen($ipSeek) < 3) {
                        fclose($fd);
                        return 'System Error';
                    }
                    $ipSeek = implode('', unpack('L', $ipSeek . chr(0)));
                    fseek($fd, $ipSeek);
                    $ipFlag = fread($fd, 1);
                }
                if ($ipFlag == chr(2)) {
                    $AddrSeek = fread($fd, 3);
                    if (strlen($AddrSeek) < 3) {
                        fclose($fd);
                        return 'System Error';
                    }
                    $ipFlag = fread($fd, 1);
                    if ($ipFlag == chr(2)) {
                        $AddrSeek2 = fread($fd, 3);
                        if (strlen($AddrSeek2) < 3) {
                            fclose($fd);
                            return 'System Error';
                        }
                        $AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
                        fseek($fd, $AddrSeek2);
                    } else {
                        fseek($fd, -1, SEEK_CUR);
                    }
                    while (($char = fread($fd, 1)) != chr(0)) {
                        $ipAddr2 .= $char;
                    }

                    $AddrSeek = implode('', unpack('L', $AddrSeek . chr(0)));
                    fseek($fd, $AddrSeek);
                    while (($char = fread($fd, 1)) != chr(0)) {
                        $ipAddr1 .= $char;
                    }

                } else {
                    fseek($fd, -1, SEEK_CUR);
                    while (($char = fread($fd, 1)) != chr(0)) {
                        $ipAddr1 .= $char;
                    }

                    $ipFlag = fread($fd, 1);
                    if ($ipFlag == chr(2)) {
                        $AddrSeek2 = fread($fd, 3);
                        if (strlen($AddrSeek2) < 3) {
                            fclose($fd);
                            return '- System Error';
                        }
                        $AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
                        fseek($fd, $AddrSeek2);
                    } else {
                        fseek($fd, -1, SEEK_CUR);
                    }
                    while (($char = fread($fd, 1)) != chr(0)) {
                        $ipAddr2 .= $char;
                    }

                }
                fclose($fd);
                if (preg_match('/http/i', $ipAddr2)) {
                    $ipAddr2 = '';
                }
                $ipaddr = "$ipAddr1 $ipAddr2";
                $ipaddr = preg_replace('/CZ88\.NET/is', '', $ipaddr);
                $ipaddr = preg_replace('/^\s*/is', '', $ipaddr);
                $ipaddr = preg_replace('/\s*$/is', '', $ipaddr);
                if (preg_match('/http/i', $ipaddr) || $ipaddr == '') {
                    $ipaddr = 'Unknown';
                }
                $return = explode(' ', $ipaddr)[0];
            }
        }
        return mb_convert_encoding($return, 'utf-8', 'GB2312');
    }

    public static function clientIp() {
        if ( function_exists( 'apache_request_headers' ) ) {
            $headers = apache_request_headers();
        } else {
            $headers = $_SERVER;
        }
        if ( array_key_exists( 'X-Forwarded-For', $headers ) && filter_var( explode(',', $headers['X-Forwarded-For'])[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
            $theIp = explode(',', $headers['X-Forwarded-For'])[0];
        } elseif ( array_key_exists( 'HTTP_X_FORWARDED_FOR', $headers ) && filter_var( explode(',', $headers['HTTP_X_FORWARDED_FOR'])[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 )
        ) {
            $theIp = explode(',', $headers['HTTP_X_FORWARDED_FOR'])[0];
        } else {
            $theIp = filter_var( $_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 );
        }
        return $theIp;
    }
}
